/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.rum.sender.command.Factory;

import cz.muni.fi.rum.sender.SenderException;
import cz.muni.fi.rum.sender.command.RapRequest;
import cz.muni.fi.rum.sender.command.RapResponse;
import cz.muni.fi.rum.sender.command.Request;
import cz.muni.fi.rum.sender.command.Response;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author pmikulasek
 */
public class CommandFactoryImpl implements CommandFactory {

    private static CommandFactory instance;
    private static final Logger logger = Logger.getLogger(CommandFactoryImpl.class.getName());
//C:\Users\pmikulasek\Documents\JAVAProjekty\OstreProjekty\RUM2\src\main\resources\cz\muni\fi\rum\sender\resources\requests.properties
    private static final String PATH = "/cz/muni/fi/rum/sender/resources/requests.properties";
    private static final String START_VALUE_SEPARATOR = "${";
    private static final String END_VALUE_SEPARATOR = "}";
    private static final String LINE_SEPARATOR = "\n";
    private Properties properties;

    private CommandFactoryImpl() {
        this.properties = loadProperties();
    }

    public static CommandFactory getInstance() {
        if (instance == null) {
            instance = new CommandFactoryImpl();
        }
        return instance;
    }

    /**
     * Ze zadane cesty vytvori Properties
     * @param path classpath resource name [may not be null]
     * @return resource converted to java.util.Properties
     */
    private Properties loadProperties() {
        Properties result = null;
        InputStream inputStream = null;
        try {
            result = new Properties();
            inputStream = this.getClass().getResourceAsStream(PATH);
            result.load(inputStream);
            inputStream.close();
        } catch (Exception e) {
            result = null;
            logger.log(Level.WARNING, "Nejde nacist soubor \"{0}\"", e);
//            throw new IOException(e);
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException ex) {
                    logger.log(Level.WARNING, "Nejde zavrit InputStream", ex);
                }
            }
        }
        return result;
    }

    /**
     * POZOR metoda neakceptuje vice parametru na jednom radku!
     * @param key
     * @param params
     * @return
     */
    @Override
    public RapRequest createRequest(String key, Map<String, String> params) throws SenderException {
        String property = properties.getProperty(key);
        if (property != null) {
            StringBuilder buf = new StringBuilder(property);
            int startIndex = buf.indexOf(START_VALUE_SEPARATOR);
            int startLineIndex = -1;
            while (startIndex > -1) {
                int endIndex = buf.indexOf(END_VALUE_SEPARATOR, startIndex);
                String subKey = buf.substring(startIndex + START_VALUE_SEPARATOR.length(), endIndex);
                int endLineIndex;
                if (properties.containsKey(subKey)) {
                    buf.replace(startIndex, endIndex + END_VALUE_SEPARATOR.length(), properties.getProperty(subKey));
                    startLineIndex = buf.indexOf(LINE_SEPARATOR, startIndex) + LINE_SEPARATOR.length();
                    startIndex = buf.indexOf(START_VALUE_SEPARATOR, startIndex);
                } else if (params.containsKey(subKey)) {
                    buf.replace(startIndex, endIndex + END_VALUE_SEPARATOR.length(), params.get(subKey));
                    startLineIndex = buf.indexOf(LINE_SEPARATOR, startIndex) + LINE_SEPARATOR.length();
                    startIndex = buf.indexOf(START_VALUE_SEPARATOR, startIndex);
                } else {
                    endLineIndex = buf.indexOf(LINE_SEPARATOR, endIndex) + LINE_SEPARATOR.length();
                    buf.delete(startLineIndex == -1 ? 0 : startLineIndex, endLineIndex);
                    startIndex = buf.indexOf(START_VALUE_SEPARATOR, startLineIndex);
                }
            }
            return new Request(buf.toString());
        } else {
            throw new SenderException("Klic: \""+ key +"\" nebyl nalezen.");
        }
    }

    @Override
    public RapResponse createResponse(String value) {
        return new Response(value);
    }
}
